﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.IO;

namespace Snake
{
	/// <summary>
	/// A játéktáblát reprezentáló osztály
	/// </summary>
	public class gameTable : Panel
	{
		/// <summary>
		/// A játékterep objektumait tárolja, úgy mint a fal és az alma
		/// </summary>
		protected List<gameObject> gameObjects;

		/// <summary>
		/// Az éppen játszó játékos adatait tárolja
		/// </summary>
		protected Player player;

		/// <summary>
		/// Egy "interface" az éppen játszó játékos kígyójához
		/// </summary>
		protected snakeObject snake
		{
			get
			{
				if (player != null)
					return player.snake;
				else return null;
			}
			set
			{
				player.snake = value;
			}
		}

		/// <summary>
		/// A kígyót mozgató időzítő
		/// </summary>
		protected Timer timer;

		/// <summary>
		/// A játéktábla méretét lehet ezen keresztül megadni
		/// </summary>
		public Size tableSize { get; set; }

		/// <summary>
		/// Az osztály konstruktora
		/// </summary>
		public gameTable()
		{
			Paint += new PaintEventHandler(Render);

			timer = new Timer();
			timer.Interval = 50;
			timer.Tick += delegate(object sender, EventArgs e)
							{
								if (!snake.isDead)
								{
									snake.move();
                                    Refresh();
									updateLevel();
								}

							};

			this.SetStyle(ControlStyles.ResizeRedraw, true);
			this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
			this.SetStyle(ControlStyles.UserPaint, true);
			this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
		}

		/// <summary>
		/// A megjelenítésért felelős eljárás. Ezt az eljárást hívja meg az osztályt használó ablak a játéktábla kirajzolásához
		/// </summary>
		/// <param name="sender">Az üzenetküldőre mutató referencia</param>
		/// <param name="e">Kirajzolási paramétereket lehet ezen keresztül megadni</param>
		void Render(object sender, PaintEventArgs e)
		{
			Graphics g = e.Graphics;

			if (gameObjects != null)
			{
				g.Clear(Color.White);
				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

				g.ScaleTransform((float)(sender as Control).Width / tableSize.Width, (float)(sender as Control).Height / tableSize.Height);

				Pen pen = new Pen(Color.Black, 0.1f);


				foreach (gameObject obj in gameObjects)
				{
					obj.Paint(g);
				}

				if (snake != null)
				{
					snake.Paint(g);

					if (snake.isDead)
					{
						StringFormat format = new StringFormat();
						format.Alignment = StringAlignment.Center;
						format.LineAlignment = StringAlignment.Center;

						Font font = new Font("Arial", 12, GraphicsUnit.Document);
						g.DrawString("Vesztettél!", font, Brushes.Black, new RectangleF(0, 0, tableSize.Width, tableSize.Height), format);

					}
				}

				if (player != null)
				{
					Font font = new Font("Arial", 4, GraphicsUnit.Document);
					StringFormat format = new StringFormat();
					format.Alignment = StringAlignment.Far;
					g.DrawString(player.points.ToString() + " pont", font, Brushes.LightGreen, new RectangleF(0, 1, tableSize.Width - 1, tableSize.Height), format);
				}
			}
			else
			{
				g.Clear(Color.Gray);
			}
		}

		public void generateTable()
		{
		}

		/// <summary>
		/// A játéktáblát ezen keresztül lehet inicializálni.
		/// Kötelező meghívni, ha használni akarjuk!
		/// </summary>
		public void initGame()
		{
			tableSize = new Size(70, 40);

			player = new Player();

			snake = new snakeObject();
			snake.DieEvent += delegate(snakeObject obj)
			{
				nameBox namebox = new nameBox();
				namebox.ShowDialog();
                if (namebox.Tag != null)
                {
                    player.name = namebox.Tag.ToString();
                }
                else
                {
                    player.name = "";
                }
				saveTopList();
				loadTopList();
			};
			gameObjects = new List<gameObject>();

			Random random = new Random();

			gameObjects.Add(new apple() { position = new Point(random.Next(1, tableSize.Width - 1), random.Next(1, tableSize.Height - 1)) });

			for (int i = 0; i < tableSize.Width; ++i)
			{
				this.gameObjects.Add(new wall() { position = new Point(i, 0) });
				this.gameObjects.Add(new wall() { position = new Point(i, tableSize.Height - 1) });
			}

			for (int i = 0; i < tableSize.Height; ++i)
			{
				this.gameObjects.Add(new wall() { position = new Point(0, i) });
				this.gameObjects.Add(new wall() { position = new Point(tableSize.Width - 1, i) });
			}

			timer.Start();
		}

		/// <summary>
		/// A játék toplistáját ezen az eljáráson keresztül lehet betölteni.
		/// </summary>
		public void loadTopList()
		{
			FileInfo fileInfo = new FileInfo("toplist");
			if (fileInfo.Exists)
			{
				StreamReader stream = fileInfo.OpenText();
				List<Player> players = new List<Player>();
				while (!stream.EndOfStream)
				{
					string line = stream.ReadLine();
					players.Add(Player.Parse(line));
				}
				toplistWindow window = new toplistWindow(players.ToArray(), player);
				window.Show();
			}
		}

		/// <summary>
		/// A játék toplistáját ezen az eljáráson keresztül lehet elmenteni.
		/// </summary>
		public void saveTopList()
		{
			FileInfo fileInfo = new FileInfo("toplist");
			if (!fileInfo.Exists)
			{
				StreamWriter stream = fileInfo.CreateText();
				stream.WriteLine(player.ToString());
				stream.Close();
			}
			else
			{
				StreamReader stream = fileInfo.OpenText();
				List<Player> list = new List<Player>();
				bool L = false;

				while (!stream.EndOfStream)
				{
					Player current = Player.Parse(stream.ReadLine());
					if (!L && current.points < player.points)
					{
						list.Add(player);
						L = true;
					}
					list.Add(current);
				}

				if (!L)
				{
					list.Add(player);
				}

				stream.Close();

				StreamWriter write = fileInfo.CreateText();
				foreach (Player p in list)
				{
					write.WriteLine(p.ToString());
				}
				write.Close();
			}
		}

		/// <summary>
		/// A kígyó irányításáért felelős eljárás.
		/// </summary>
		/// <param name="sender">A küldő referenciáját itt kapja meg az eljárás</param>
		/// <param name="e">A lenyomott gombok adatait ezen keresztül kapja meg az eljárás</param>
		public void ManageControl(object sender, KeyEventArgs e)
		{
			snake.ManageControl(sender, e);
		}

		/// <summary>
		/// A játék közben történő eseményekért felelős eljárás.
		/// </summary>
		public void updateLevel()
		{
			if (snake.isIntersected())
			{
				snake.isDead = true;
			}
			else
			{
				int i = 0;
				while (i < gameObjects.Count && !snake.isIntersected(gameObjects[i]))
				{
					++i;
				}
				if (i < gameObjects.Count)
				{
					if (gameObjects[i] is apple)
					{
						snake.grow();
						player.points += 100;
						Random random = new Random();
						gameObjects[i].position = new Point(random.Next(1, tableSize.Width - 1), random.Next(1, tableSize.Height - 1));
					}
					else if (gameObjects[i] is wall)
					{
						snake.isDead = true;
					}
				}
			}
		}

	}
}
